using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace QuadAnimation.Primitives.Shapes
{
    public class Quad
    {
        #region Member Variables
        VertexPositionNormalTexture[] vertices;
        int[] indices;

        Vector3 origin;
        Vector3 normal;
        Vector3 up;

        //Relative positions
        Vector3 left;
        Vector3 upperLeft;
        Vector3 upperRight;
        Vector3 lowerLeft;
        Vector3 lowerRight;

        //Texture coordinates
        Vector2 textureUpperLeft;
        Vector2 textureUpperRight;
        Vector2 textureLowerLeft;
        Vector2 textureLowerRight;
        #endregion

        #region Properties
        public VertexPositionNormalTexture[] Vertices
        {
            get { return vertices; }
        }

        public int[] Indices
        {
            get { return indices; }
        }
        #endregion

        /// <summary>
        /// Constructor for a textured Quad
        /// </summary>
        /// <param name="origin">Centre of quad in world space</param>
        /// <param name="normal">Direction the quad is facing</param>
        /// <param name="up">Normalized vector representing up</param>
        /// <param name="width">Width of the quad</param>
        /// <param name="height">Height of the quad</param>
        public Quad(Vector3 origin, Vector3 normal, Vector3 up, float width, float height)
        {
            this.origin = origin;
            this.normal = normal;
            this.up = up;

            //Only using 4 because we share common points
            vertices = new VertexPositionNormalTexture[4];

            //Using 6 indices
            indices = new int[6];

            //Right hand coordinate system
            left = Vector3.Cross(normal, up);

            Vector3 upperCenter = origin + (up * height / 2);

            upperLeft = upperCenter + (left * (width / 2));
            upperRight = upperCenter - (left * (width / 2));
            lowerLeft = upperLeft - (up * height);
            lowerRight = upperRight - (up * height);

            //Fill out the vertex information
            FillVertices();
        }

        private void FillVertices()
        {
            //Setup the texture coordinates
            SetTextureCoordinates(new Vector2(0, 0), new Vector2(1, 0),
                new Vector2(1, 1), new Vector2(0, 1), false);
            
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i].Normal = normal;
            }

            vertices[0].Position = upperLeft;
            vertices[1].Position = upperRight;
            vertices[2].Position = lowerRight;
            vertices[3].Position = lowerLeft;

            SetIndices();
        }

        /// <summary>
        /// Sets the indices for the vertex list
        /// </summary>
        private void SetIndices()
        {
            indices[0] = 0;
            indices[1] = 1;
            indices[2] = 2;
            indices[3] = 2;
            indices[4] = 3;
            indices[5] = 0;
        }

        public void SetTextureCoordinates(Vector2 upperLeft, Vector2 upperRight,
            Vector2 lowerRight, Vector2 lowerLeft, Boolean flip)
        {
            if (flip)
            {
                textureUpperLeft = upperRight;
                textureUpperRight = upperLeft;
                textureLowerRight = lowerLeft;
                textureLowerLeft = lowerRight;
            }
            else
            {
                textureUpperLeft = upperLeft;
                textureUpperRight = upperRight;
                textureLowerRight = lowerRight;
                textureLowerLeft = lowerLeft;
            }

            vertices[0].TextureCoordinate = textureUpperLeft;
            vertices[1].TextureCoordinate = textureUpperRight;
            vertices[2].TextureCoordinate = textureLowerRight;
            vertices[3].TextureCoordinate = textureLowerLeft;
        }
    }
}
